package org.jmc.refmanager.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementMap;
import org.simpleframework.xml.Root;

@Root(name="changes")
public class UpdatesList implements Serializable {
	private static final long serialVersionUID = 1L;
	@Attribute(required=true)
	private Integer serviceId;
	
	/**
	 * Contient les groupes de modification e traiter ensemble
	 *
	 */
	public enum UpdateType {
		ADDRESS, LABEL, PARENT, OTHER
	}

	@ElementMap(entry="change", key="type", attribute=true, inline=true)
	private Map<UpdateType, Update> updates = new HashMap<UpdateType, Update>();

	/**
	 * 
	 */
	public UpdatesList() {
		super();
		
		for (UpdateType type : UpdateType.values()) {
			Update update = new Update();
			updates.put(type, update);
		}
	}

	/**
	 * @return the serviceId
	 */
	public Integer getServiceId() {
		return serviceId;
	}

	/**
	 * 
	 * @param serviceId
	 */
	public void setServiceId(Integer serviceId) {
		this.serviceId = serviceId;
	}
	
	/**
	 * 
	 * @param type
	 * @return
	 */
	public boolean containsUpdateOf(UpdateType type) {
		Update update = updates.get(type);
		return update != null && !update.isEmpty();
	}


	/**
	 * 
	 * @return
	 */
	public UpdatesList trim() {
		Iterator<Entry<UpdateType, Update>> it = updates.entrySet().iterator();
		while (it.hasNext()) {
			Entry<UpdateType, Update> entry =  it.next();
			if (entry.getValue() != null && entry.getValue().isEmpty()) {
				it.remove();
			}
		}
		
		return this;
	}

	/**
	 * Liste de tous les changements sans ceux du mouvement.
	 * 
	 * @return
	 */
	public List<Update> getAllUpdatesWithNoMove() {
		List<Update> notNullUpdates = new ArrayList<Update>();
		for (Entry<UpdateType, Update> entry : updates.entrySet()) {
			if (entry != null && entry.getKey() != UpdateType.PARENT) {
				Update update = entry.getValue();
				
				if (update != null && !update.isEmpty()) {
					notNullUpdates.add(update);
				}
			}
		}
		
		return Collections.unmodifiableList(notNullUpdates);
	}
	
	/**
	 * Retourne la valeur un attribut mis e jour
	 * 
	 * @param attrName
	 * @return
	 */
	public Update getUpdate(String attrName) {
		Update updateValue = null;
		for (Entry<UpdateType, Update> entry : updates.entrySet()) {
			Update update = entry.getValue();
			if (update != null && !update.isEmpty()) {
				if (update.getAttributeUpdates().containsKey(attrName)) {
					updateValue = update;
					break;
				}
			}
		}
		
		return updateValue;
	}

	/**
	 * 
	 * @param attrName
	 * @return
	 */
	public boolean containsUpdateAttribute(String attrName) {
		boolean exist = false;
		for (Entry<UpdateType, Update> entry : updates.entrySet()) {
			Update update = entry.getValue();
			if (update != null && !update.isEmpty()) {
				if (update.getAttributeUpdates().containsKey(attrName)) {
					exist = true;
					break;
				}
			}
		}
		
		return exist;
	}

	/**
	 * 
	 * @param type
	 * @return
	 */
	public Update getUpdateOf(UpdateType type) {
		return updates.get(type);
	}

}
